<?php
/**
 * DBShop 电子商务系统
 *
 * ==========================================================================
 * @link      https://www.dbshop.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   https://www.dbshop.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace Goods\Event;

use Admin\Data\Common;
use Admin\Data\Config;
use Doctrine\ORM\EntityManager;
use Goods\Entity\GoodsSpecTag;
use Goods\Entity\GoodsSpecTagGoods;
use Goods\Service\GoodsConsultationManager;
use Goods\Service\GoodsInSpecImageManager;
use Goods\Service\GoodsInTagManager;
use Goods\Service\GoodsSpecTagGoodsManager;
use Goods\Service\GoodsSpecTagManager;
use Laminas\EventManager\Event;
use Laminas\EventManager\EventManagerInterface;
use Laminas\EventManager\ListenerAggregateInterface;
use Laminas\Mvc\I18n\Translator;

class GoodsListener implements ListenerAggregateInterface
{
    protected $listeners = [];

    private $entityManager;
    private $goodsInTagManager;
    private $goodsInSpecImageManager;
    private $goodsConsultationManager;
    private $goodsSpecTagGoodsManager;
    private $goodsSpecTagManager;

    private $translator;

    public function __construct(
        EntityManager   $entityManager,
        GoodsInTagManager $goodsInTagManager,
        GoodsInSpecImageManager $goodsInSpecImageManager,
        GoodsConsultationManager $goodsConsultationManager,
        GoodsSpecTagGoodsManager $goodsSpecTagGoodsManager,
        GoodsSpecTagManager $goodsSpecTagManager,
        Translator      $translator
    )
    {
        $this->entityManager = $entityManager;
        $this->goodsInTagManager = $goodsInTagManager;
        $this->goodsInSpecImageManager  = $goodsInSpecImageManager;
        $this->goodsConsultationManager = $goodsConsultationManager;
        $this->goodsSpecTagGoodsManager = $goodsSpecTagGoodsManager;
        $this->goodsSpecTagManager      = $goodsSpecTagManager;

        $this->translator   = $translator;
    }

    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $shareEvents = $events->getSharedManager();

        //商品编辑时的处理
        $this->listeners[] = $shareEvents->attach(
            'Goods\Controller\IndexController', 'goods.edit.post', [$this, 'onEditGoodsOther']
        );

        //标签删除时，同时删除商品中绑定的该标签
        $this->listeners[] = $shareEvents->attach(
            'Goods\Controller\GoodsTagController', 'tag.delete.post', [$this, 'onDeleteGoodsInTag']
        );
        //商品图片删除时，同时删除规格里面的图片
        $this->listeners[] = $shareEvents->attach(
            'Goods\Controller\IndexController', 'goodsImage.delete.post', [$this, 'onDeleteGoodsSpecImage']
        );
        //商品删除时，删除处理
        $this->listeners[] = $shareEvents->attach(
            'Goods\Controller\IndexController', 'goods.delete.post', [$this, 'onDeleteGoodsOther']
        );

        //后台添加商品时，页面显示特定显示
        $this->listeners[] = $shareEvents->attach(
            'Goods\Controller\IndexController', 'goods.add.show', [$this, 'goodsExtendSpecTagShow']
        );
        //后台添加保存商品时，处理特定标签保存
        $this->listeners[] = $shareEvents->attach(
            'Goods\Controller\IndexController', 'goods.add.post', [$this, 'goodsExtendSpecTagSave']
        );
        //后台编辑商品时，页面显示特定显示
        $this->listeners[] = $shareEvents->attach(
            'Goods\Controller\IndexController', 'goods.edit.show', [$this, 'goodsExtendSpecTagShow']
        );
        //后台编辑保存商品时，处理特定标签保存
        $this->listeners[] = $shareEvents->attach(
            'Goods\Controller\IndexController', 'goods.edit.post', [$this, 'goodsExtendSpecTagSave']
        );
    }

    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            $events->detach($listener);
            unset($this->listeners[$index]);
        }
    }

    /**
     * 商品编辑时的处理
     * @param Event $event
     */
    public function onEditGoodsOther(Event $event)
    {
        $goodsId = (int) $event->getParam('goodsId');
        if($goodsId > 0) {
            //分享海报删除
            Common::deleteDirAndFile(Config::GOODS_QRCODE_IMAGE_PATH . $goodsId, false);
        }
    }

    /**
     * 标签删除时，同时删除商品中绑定的该标签
     * @param Event $event
     */
    public function onDeleteGoodsInTag(Event $event)
    {
        $tagIdArray = $event->getParams();
        if(!empty($tagIdArray)) foreach ($tagIdArray as $tagId) {
            $this->goodsInTagManager->deleteTagIdGoods(intval($tagId));
        }
    }

    /**
     * 商品图片删除时，同时删除规格里面的图片
     * @param Event $event
     */
    public function onDeleteGoodsSpecImage(Event $event)
    {
        $goodsImageId = (int) $event->getParam('goodsImageId');
        if($goodsImageId > 0) $this->goodsInSpecImageManager->deleteMoreSpecImage($goodsImageId);
    }

    /**
     * 删除商品下的内容
     * 1)商品咨询
     * 2)海报删除
     * @param Event $event
     */
    public function onDeleteGoodsOther(Event $event)
    {
        $goodsId = (int) $event->getParam('goodsId');
        if($goodsId > 0) {
            //特定标签商品
            $this->goodsSpecTagGoodsManager->deleteMoreSpecTagGoods($goodsId);
            //商品咨询
            $this->goodsConsultationManager->deleteOneGoodsMoreConsult($goodsId);
            //分享海报
            Common::deleteDirAndFile(Config::GOODS_QRCODE_IMAGE_PATH.$goodsId);
        }
    }

    /**
     * 后台添加或编辑商品时，页面显示特定显示
     * @param Event $event
     * @return array|mixed
     */
    public function goodsExtendSpecTagShow(Event $event)
    {
        $mobileTemplateSpecTag  = Common::getDefaultTemplateTag('goodsSpecTag');
        $pcTemplateSpecTag      = Common::getDefaultTemplateTag('goodsSpecTag', 'pcTemplate');

        $array      = $event->getParams();
        $lastArray  = $event->getParam('lastArray');
        $goodsType  = $event->getParam('goodsType');
        $form       = $event->getParam('form');

        if (!empty($pcTemplateSpecTag)) {
            $form->add([
                'type'  => 'multiCheckbox',
                'name'  => 'pcSpecTagCode',
                'options' => [
                    'value_options' => $pcTemplateSpecTag,

                    'label_attributes' => [
                        'class' => 'checkbox-inline'
                    ]
                ]
            ]);

            $form->inputFilter->add([
                'name'      => 'pcSpecTagCode',
                'required'  => false
            ]);

            $lastArray['formExtend'][] = [
                'inputTitle'    => $this->translator->translate(sprintf('%s特定标签显示%s(电脑前台)', '<a href="'.$event->getTarget()->url()->fromRoute('goods-spec-tag').'" target="_blank">', '</a>')),
                'inputName'     => 'pcSpecTagCode',
                'classSpanNum'  => 10
            ];

            if ($goodsType == 'edit' && !$event->getTarget()->getRequest()->isPost()) {
                $pcSpecTagGoodsList = $this->entityManager->getRepository(GoodsSpecTagGoods::class)->findBy(['goodsId' => $event->getParam('goodsId'), 'templateCode' => Common::getDefaultTemplateCode('pcTemplate')]);
                $pcSpecTagGoodsArray= [];
                if ($pcSpecTagGoodsList) foreach ($pcSpecTagGoodsList as $tagGoodsValue) {
                    if (isset($pcTemplateSpecTag[$tagGoodsValue->getSpecTagCode()])) $pcSpecTagGoodsArray[] = $tagGoodsValue->getSpecTagCode();
                }
                if (!empty($pcSpecTagGoodsArray)) {
                    $form->setData([
                        'pcSpecTagCode' => $pcSpecTagGoodsArray
                    ]);
                }
            }
        }

        if (!empty($mobileTemplateSpecTag)) {
            $form->add([
                'type'  => 'multiCheckbox',
                'name'  => 'mobileSpecTagCode',
                'options' => [
                    'value_options' => $mobileTemplateSpecTag,

                    'label_attributes' => [
                        'class' => 'checkbox-inline'
                    ]
                ]
            ]);

            $form->inputFilter->add([
                'name'      => 'mobileSpecTagCode',
                'required'  => false
            ]);

            $lastArray['formExtend'][] = [
                'inputTitle'    => $this->translator->translate(sprintf('%s特定标签显示%s(手机前台)', '<a href="'.$event->getTarget()->url()->fromRoute('goods-spec-tag').'" target="_blank">', '</a>')),
                'inputName'     => 'mobileSpecTagCode',
                'classSpanNum'  => 10
            ];

            if ($goodsType == 'edit' && !$event->getTarget()->getRequest()->isPost()) {
                $mobileSpecTagGoodsList = $this->entityManager->getRepository(GoodsSpecTagGoods::class)->findBy(['goodsId' => $event->getParam('goodsId'), 'templateCode' => Common::getDefaultTemplateCode()]);
                $mobileSpecTagGoodsArray= [];
                if ($mobileSpecTagGoodsList) foreach ($mobileSpecTagGoodsList as $tagGoodsValue) {
                    if (isset($mobileTemplateSpecTag[$tagGoodsValue->getSpecTagCode()])) $mobileSpecTagGoodsArray[] = $tagGoodsValue->getSpecTagCode();
                }
                if (!empty($mobileSpecTagGoodsArray)) {
                    $form->setData([
                        'mobileSpecTagCode' => $mobileSpecTagGoodsArray
                    ]);
                }
            }
        }

        $array['lastArray'] = $lastArray;
        $array['form']      = $form;
        $event->setParams($array);

        $lastArray['form'] = $form;
        return $lastArray;
    }

    /**
     * 后台编辑保存商品时，处理特定标签保存
     * @param Event $event
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function goodsExtendSpecTagSave(Event $event) {
        $goodsId    = $event->getParam('goodsId');
        $postData   = $event->getParam('postData');

        $pcTemplateCode = Common::getDefaultTemplateCode('pcTemplate');
        if (isset($postData['pcSpecTagCode']) && !empty($postData['pcSpecTagCode'])) {
            $goodsSpecTagArray = Common::getDefaultTemplateTag('goodsSpecTag', 'pcTemplate');
            foreach ($postData['pcSpecTagCode'] as $key => $pcTagCode) {
                if (!isset($goodsSpecTagArray[$pcTagCode])) {
                    unset($postData['pcSpecTagCode'][$key]);
                    continue;
                }

                $tagSort        = stripos(implode(',', $goodsSpecTagArray), $goodsSpecTagArray[$pcTagCode]);
                $specTagInfo    = $this->entityManager->getRepository(GoodsSpecTag::class)->findOneBy(['specTagCode' => $pcTagCode, 'templateCode' => $pcTemplateCode]);
                if ($specTagInfo == null) {
                    $specTagInfo = $this->goodsSpecTagManager->addSpecTag([
                        'specTagName' => $goodsSpecTagArray[$pcTagCode],
                        'specTagCode' => $pcTagCode,
                        'specTagSort' => $tagSort,
                        'templateCode'=> $pcTemplateCode
                    ]);
                } elseif($specTagInfo->getSpecTagSort() != $tagSort) $specTagInfo = $this->goodsSpecTagManager->editSpecTag(['specTagSort' => $tagSort], $specTagInfo);

                $specGoods = $this->entityManager->getRepository(GoodsSpecTagGoods::class)->findOneBy(['specTagId' => $specTagInfo->getSpecTagId(), 'goodsId' => $goodsId, 'specTagCode' => $pcTagCode, 'templateCode' => $pcTemplateCode]);
                if ($specGoods == null) {
                    $this->goodsSpecTagGoodsManager->addSpecTagGoods(['specTagId' => $specTagInfo->getSpecTagId(), 'goodsId' => $goodsId, 'specTagGoodsSort' => 255, 'specTagCode' => $pcTagCode, 'templateCode' => $pcTemplateCode]);
                }
            }
        }
        if (!empty($pcTemplateCode)) $this->goodsSpecTagGoodsManager->deleteNotExistsSpecTagGoods($goodsId, $pcTemplateCode, $postData['pcSpecTagCode'] ?? []);

        $mobileTemplateCode = Common::getDefaultTemplateCode();
        if (isset($postData['mobileSpecTagCode']) && !empty($postData['mobileSpecTagCode'])) {
            $goodsSpecTagArray  = Common::getDefaultTemplateTag('goodsSpecTag');

            foreach ($postData['mobileSpecTagCode'] as $key => $mobileTagCode) {
                if (!isset($goodsSpecTagArray[$mobileTagCode])) {
                    unset($postData['mobileSpecTagCode'][$key]);
                    continue;
                }

                $tagSort        = stripos(implode(',', $goodsSpecTagArray), $goodsSpecTagArray[$mobileTagCode]);
                $specTagInfo    = $this->entityManager->getRepository(GoodsSpecTag::class)->findOneBy(['specTagCode' => $mobileTagCode, 'templateCode' => $mobileTemplateCode]);
                if ($specTagInfo == null) {
                    $specTagInfo = $this->goodsSpecTagManager->addSpecTag([
                        'specTagName' => $goodsSpecTagArray[$mobileTagCode],
                        'specTagCode' => $mobileTagCode,
                        'specTagSort' => $tagSort,
                        'templateCode'=> $mobileTemplateCode
                    ]);
                } elseif($specTagInfo->getSpecTagSort() != $tagSort) $specTagInfo = $this->goodsSpecTagManager->editSpecTag(['specTagSort' => $tagSort], $specTagInfo);

                $specGoods = $this->entityManager->getRepository(GoodsSpecTagGoods::class)->findOneBy(['specTagId' => $specTagInfo->getSpecTagId(), 'goodsId' => $goodsId, 'specTagCode' => $mobileTagCode, 'templateCode' => $mobileTemplateCode]);
                if ($specGoods == null) {
                    $this->goodsSpecTagGoodsManager->addSpecTagGoods(['specTagId' => $specTagInfo->getSpecTagId(), 'goodsId' => $goodsId, 'specTagGoodsSort' => 255, 'specTagCode' => $mobileTagCode, 'templateCode' => $mobileTemplateCode]);
                }
            }
        }
        if (!empty($mobileTemplateCode)) $this->goodsSpecTagGoodsManager->deleteNotExistsSpecTagGoods($goodsId, $mobileTemplateCode, $postData['mobileSpecTagCode'] ?? []);
    }
}